package CassroomPractice.DoubleLinkedlist;

import CassroomPractice.SingiyLinkedlist.ListOperation;
import CassroomPractice.SingiyLinkedlist.SinglyNode;

import java.util.NoSuchElementException;
import java.util.Objects;

public class DoubleList<E> implements ListOperation<E> {

    private  DoubleNode<E> head;
    private  DoubleNode<E> tail;
    private int size;


    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public void addFirst(E item) {
        if (isEmpty()){
            head = new DoubleNode<>(item);
            tail = head;
        }else {
            head = new DoubleNode<>(null,item,head);
            head.next.last = head;
        }
        size++;
    }

    @Override
    public void addLast(E item) {
        if (isEmpty()){
            addFirst(item);
            return;
        }else {
            tail = new DoubleNode<>(tail, item, null);
            tail.last.next = tail;
        }
        size++;
    }

    @Override
    public void add(int index, E item) {
        if (index == 0){
            addFirst(item);
            return;
        }

        if (index < 0 || index >= size){
            throw new IndexOutOfBoundsException("输入不合法");
        }

        DoubleNode<E> temp = head;
        for (int i = 0; i < index; i++) {
            temp = temp.next;
        }

        temp.last.next = new DoubleNode<>(temp.last,item,temp);
        temp.last = temp.last.next;
        size++;

    }

    @Override
    public E getFirst() {
        if (isEmpty()){
            throw new NoSuchElementException("链表为空");
        }
        return head.value;
    }

    @Override
    public E getLast() {
        if (isEmpty()){
            throw new NoSuchElementException("链表为空");
        }
        return tail.value;
    }

    @Override
    public E get(int index) {

        if (index < 0 || index >= size){
            throw new IndexOutOfBoundsException("输入不合法");
        }

        DoubleNode<E> temp = head;
        for (int i = 0; i < index; i++) {
            temp = temp.next;
        }

        return temp.value;

    }

    @Override
    public E set(int index, E item) {
        if (index < 0 || index >= size){
            throw new IndexOutOfBoundsException("输入不合法");
        }

        DoubleNode<E> temp = head;
        for (int i = 0; i < index; i++) {
            temp = temp.next;
        }

        E old = temp.value;
        temp.value = item;
        return old;

    }

    @Override
    public E removeFirst() {
        if (isEmpty()){
            throw new NoSuchElementException("链表为空");
        }

        E first = head.value;
        if (size == 1){
            head = null;
            tail = null;
        }else {
            head = head.next;
            head.last = null;
        }
        size--;
        return first;
    }

    @Override
    public E removeLast() {
        if (isEmpty()){
            throw new NoSuchElementException("链表为空");
        }

        E last = tail.value;
        if (size == 1){
            head = null;
            tail = null;
        }else {
            tail = tail.last;
            tail.next = null;
        }

        size--;
        return last;
    }

    @Override
    public E remove(int index) {
        if (index < 0 || index >= size){
            throw new IndexOutOfBoundsException("输入不合法");
        }

        if (index == 0){
            return removeFirst();
        }

        if (index == size - 1){
            return removeLast();
        }

        DoubleNode<E> temp = head;
        for (int i = 0; i < index; i++) {
            temp = temp.next;
        }

        E rem = temp.value;
        temp.next.last = temp.last;
        temp.last.next = temp.next;
        size--;
        return rem;
    }

    @Override
    public boolean remove(Object obj) {
        if (isEmpty()){
            throw new NoSuchElementException("链表为空");
        }

        if (Objects.equals(head.value,obj)){
            removeFirst();
            return true;
        }

        if (Objects.equals(tail.value,obj)){
            removeLast();
            return true;
        }
        DoubleNode<E> temp = head;
        while (temp.next != null){
            if (Objects.equals(temp.value,obj)){
                temp.next.last = temp.last;
                temp.last.next = temp.next;
                size--;
                return true;
            }
            temp = temp.next;
        }

        return false;
    }
}
